package com.study.connect.service.handler;

import com.study.connect.message.InvokeResultDTO;
import com.study.connect.message.ServiceInvokeDTO;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.BeanFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.SocketAddress;

/**
 * @包名称 com.study.connect.handler
 * @类描述 <pre></pre>
 * @作者 zhangbo
 * @创建时间 2020/6/13.
 * @版本 1.00
 * @修改记录 <pre>
 *     版本           修改人         修改日期         修改内容描述
 *     -----------------------------------------------------------
 *     1.00           zhangbo        2020/6/13.           类创建
 *     -----------------------------------------------------------
 * </pre>
 */
@Slf4j
@AllArgsConstructor
public class InvokeServiceHandler extends ChannelInboundHandlerAdapter {

    private BeanFactory beanFactory;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //执行invoke相关操作，调用本地方法
        log.debug("收到客户端请求消息：{}", msg);
        if (msg instanceof ServiceInvokeDTO) {
            ServiceInvokeDTO serviceInvokeDTO = (ServiceInvokeDTO) msg;
            Object bean = beanFactory.getBean(Class.forName(serviceInvokeDTO.getServiceName()));
            Class clazz = bean.getClass();
            Object invoke = null;
            InvokeResultDTO invokeResultDTO = null;
            try {
                if (null != serviceInvokeDTO.getParams() && !serviceInvokeDTO.getParams().isEmpty()) {
                    Class[] classes = new Class[serviceInvokeDTO.getParamTypes().size()];
                    for (int i = 0; i < serviceInvokeDTO.getParamTypes().size(); i++) {
                        classes[i] = serviceInvokeDTO.getParamTypes().get(i);
                    }
                    Method method = clazz.getMethod(serviceInvokeDTO.getMethodName(), classes);
                    invoke = method.invoke(bean, serviceInvokeDTO.getParams().toArray());
                } else {
                    Method method = clazz.getMethod(serviceInvokeDTO.getMethodName());
                    invoke = method.invoke(bean);
                }
                invokeResultDTO = InvokeResultDTO.createSuccessResult(invoke);
            } catch (InvocationTargetException e) {
                invokeResultDTO = InvokeResultDTO.createException(new RuntimeException(e.getTargetException()));
            }

            log.info("返回消息：{}", invokeResultDTO);
            ctx.writeAndFlush(invokeResultDTO);
        }
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        log.info("连接注册：{}", ctx);
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        log.info("客户端注册的ip地址：{}", socketAddress.toString());
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        log.error("连接断开：{}", ctx);
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        log.info("客户端下线的ip地址：{}", socketAddress.toString());
        //TODO 需要剔除该客户端的连接

    }
}
